package com.demo.socket;

import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 使用JDK 21虚线程实现的Socket服务端
 * 能够高效处理大量客户端连接
 */
public class VirtualThreadSocketServer {
    private static final int PORT = 8080;
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");

    public static void main(String[] args) {
        // 创建虚线程执行器
        try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
            try (ServerSocket serverSocket = new ServerSocket(PORT)) {
                System.out.printf("服务端启动，监听端口: %d，使用虚线程处理连接%n", PORT);
                System.out.printf("服务端主线程: %s (是否为虚线程: %b)%n",
                        Thread.currentThread().getName(),
                        Thread.currentThread().isVirtual());

                while (!Thread.currentThread().isInterrupted()) {
                    // 接受客户端连接（会在虚线程中执行）
                    Socket clientSocket = serverSocket.accept();
                    
                    // 提交客户端处理任务到虚线程执行器
                    executor.execute(() -> handleClient(clientSocket));
                }
            } catch (IOException e) {
                System.err.println("服务端异常: " + e.getMessage());
            }
        }
        System.out.println("服务端已关闭");
    }

    /**
     * 处理客户端连接
     */
    private static void handleClient(Socket clientSocket) {
        String clientInfo = clientSocket.getInetAddress() + ":" + clientSocket.getPort();
        System.out.printf("[%s] 新客户端连接: %s，处理线程: %s (是否为虚线程: %b)%n",
                LocalTime.now().format(TIME_FORMATTER),
                clientInfo,
                Thread.currentThread().getName(),
                Thread.currentThread().isVirtual());

        try (BufferedReader in = new BufferedReader(
                     new InputStreamReader(clientSocket.getInputStream(), StandardCharsets.UTF_8));
             PrintWriter out = new PrintWriter(
                     new OutputStreamWriter(clientSocket.getOutputStream(), StandardCharsets.UTF_8), true)) {

            String inputLine;
            // 读取客户端发送的消息
            while ((inputLine = in.readLine()) != null) {
                System.out.printf("[%s] 收到来自 %s 的消息: %s%n",
                        LocalTime.now().format(TIME_FORMATTER),
                        clientInfo,
                        inputLine);

                // 处理特殊命令
                if ("exit".equalsIgnoreCase(inputLine)) {
                    out.println("再见！");
                    break;
                } else if ("time".equalsIgnoreCase(inputLine)) {
                    out.println("服务器时间: " + LocalTime.now().format(TIME_FORMATTER));
                } else {
                    // 响应客户端消息
                    out.println("服务器已收到: " + inputLine);
                }
            }

            System.out.printf("[%s] 客户端 %s 断开连接%n",
                    LocalTime.now().format(TIME_FORMATTER),
                    clientInfo);

        } catch (IOException e) {
            System.err.printf("[%s] 与客户端 %s 通信出错: %s%n",
                    LocalTime.now().format(TIME_FORMATTER),
                    clientInfo,
                    e.getMessage());
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                // 忽略关闭异常
            }
        }
    }
}
